/*
 * CarRentalSimulationApp.java
 */

package com.mademoisellegeek.carrentalsimulation;

import com.mademoisellegeek.carrentalsimulation.enums.OptimisationType;
import com.mademoisellegeek.carrentalsimulation.txt.DocumentGenerator;
import com.mademoisellegeek.carrentalsimulation.txt.DocumentParser;
import java.util.HashMap;
import java.util.Map;
import org.jdesktop.application.Application;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.Action;

/**
 * The main class of the application.
 */
public class CarRentalSimulationApp extends SingleFrameApplication {

    public static String TXT_EXTENSION = ".txt";
    public static String TEST = "test";
    public static String REQUESTS = "requests";
    public static String GARAGES = "garages";
    public static String VEHICLES = "vehicles";
    public static String TOWNS = "towns";
    public static String DISTANCES = "distances";
    public static String SEPARATOR = ",";
    public static String NEWLINE = "\n";
    public static String NB_VEHICLES_KEY = "nbvehicles";
    public static String MIN_DAYS_REQUESTED_KEY = "mindaysrequested";
    public static String REGENERATE_KEY = "regenerate";
    private static String EFFICIENCY_KEY = "efficiency";
    
    /**
     * At startup create and show the main frame of the application.
     */
    @Override protected void startup() {
        show(new CarRentalSimulationView(this));
    }

    /**
     * This method is to initialize the specified window by injecting resources.
     * Windows shown in our application come fully initialized from the GUI
     * builder, so this additional configuration is not needed.
     */
    @Override protected void configureWindow(java.awt.Window root) {
    }

    /**
     * A convenient static getter for the application instance.
     * @return the instance of CarRentalSimulationApp
     */
    public static CarRentalSimulationApp getApplication() {
        return Application.getInstance(CarRentalSimulationApp.class);
    }

    /**
     * Main method launching the application.
     */
    public static void main(String[] args) {
        launch(CarRentalSimulationApp.class, args);
    }

    @Action
    public static void EfficiencyCalculation() {
        int[][] results = new int[OptimisationType.values().length][6];
        //The data is regenerated 100 times
        //The results are cumulated in the results array
        for (int i = 0; i < 100; i++) {
            Efficiency.generateDataAndAddToResults(results);
        }
        //The results are printed out as percentages
        int i = 0;
        for (OptimisationType type : OptimisationType.values()) {
            type.printDescription();
            printStatsPercentages(results[i]);
            i++;
        }
    }

    @Action
    public static void RunSimulation() {
        HashMap<String, Integer> userInput = new HashMap<String, Integer>();
        userInput.put(NB_VEHICLES_KEY, 22);
        userInput.put(MIN_DAYS_REQUESTED_KEY, 222);
        OptimisationData data = initialiseSimulationValues(userInput);
        for (OptimisationType type : OptimisationType.values()) {
            type.printDescription();
            printStats(type.run(data));
        }
    }
    
    public static OptimisationData initialiseSimulationValues(HashMap<String, Integer> userInput) {
        try {
            Map<String, Integer> townList = DocumentParser.getTownList(TOWNS + TXT_EXTENSION);
            if (userInput.get(REGENERATE_KEY) == 1) {
                //Regenerate the .txt documents if the user requires it
                DocumentGenerator generator = new DocumentGenerator();
                int nbGarages = generator.generateGarageList(townList);
                generator.generateRequestList(userInput.get(MIN_DAYS_REQUESTED_KEY), townList);
                generator.generateVehicleList(nbGarages, userInput.get(NB_VEHICLES_KEY));
            }
            //Get the information from the txt files
            int[][] distanceArray = DocumentParser.getDistanceList(townList, DISTANCES + TXT_EXTENSION);
            OptimisationData data = new OptimisationData(townList, distanceArray);
            data.setRequestList(DocumentParser.getRequestList(REQUESTS + TXT_EXTENSION));
            DocumentParser.populateVehicleDictionary(data, VEHICLES + TXT_EXTENSION);
            DocumentParser.populateGarageDictionary(data, GARAGES + TXT_EXTENSION);
            return data;
        } catch (CarRentalException e) {
            System.out.println(e.getMessage() + e.getType());
            System.exit(1);
        }
        return null;
    }

    /*
     * Print summary of simulation results
     */
    private static void printStats(int[] results) {
        System.out.println(results[0] + " requests (" + results[1] + " days)");
        System.out.println(results[2] + " cancelled requests (" + results[3] + " days)");
        System.out.println(results[4] + " additional travels (" + results[5] + " days)");
    }

    private static void printStatsPercentages(int[] results) {
        System.out.println(results[0] + " requests (" + results[1] + " days)");
        System.out.println((float) results[2] / results[0] * 100 + "% cancelled (" + (float) results[3] / results[1] * 100 + "% days)");
        System.out.println((float) results[4] / results[0] * 100 + "% additional travels (" + (float) results[5] / results[1] * 100 + "% days)");
    }

}
